// Helper Methods
//=============================
=clearfix
  &:after
    content: ""
    display: table
    clear: both
  *zoom: 1

// Grid Configuration Accessors
//=============================
$device: false !default
$devices: false !default
$grid-column-width: false !default
$grid-column-widths: false !default
$grid-gutter-width: false !default
$grid-gutter-widths: false !default
$grid-columns: 24 !default
$grid-box-sizing: content-box !default

@function default-device()
  @return $device or nth($devices, 1)

@function grid-column-width($device: default-device())
  @return $grid-column-width or nth($grid-column-widths, index($devices, $device))

@function grid-gutter-width($device: default-device())
  @return $grid-gutter-width or nth($grid-gutter-widths, index($devices, $device))

@function grid-columns($device: default-device())
  @if type-of($grid-columns) == list
    @return nth($grid-columns, index($devices, $device))
  @else
    @return $grid-columns

// Note that the gutter is only between the columns, i.e. you have 1 gutter less than columns
@function grid-gutters($device: default-device())
  @return grid-columns($device) - 1

// The default settings result in a grid-width of 990 px
@function grid-width($device: default-device())
  @return grid-column-width($device) * grid-columns($device) + grid-gutter-width($device) * grid-gutters($device)


// Public Methods
//===============

// Main Grid Helper Methods
//-------------------------
// $colspan should be the number of grid columns. You can override it with a fixed width if you must.
// You can also give a $padding and a $border-width, which is applied to both left and right by default.
// It is ensured that you do not break the grid by setting padding and a border.
// In order to differentiate between left and right padding/border-width you can set $different-right-padding/-border-width.
// Example: +grid(4, 10px, 15px) will set padding-left: 10px, padding-right: 15px and the element will have the same overall width as +grid(4).
// By default, the gutter is represented using margin-right, which can also be overridden.
=column($colspan, $device: default-device(), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $gutter: grid-gutter-width($device), $left-gutter: false, $subtract-border-from: false)
  +column-behavior
  +column-metrics($colspan, $device, $padding, $differing-right-padding, $border-width, $differing-right-border-width, $gutter, $left-gutter, $subtract-border-from: $subtract-border-from)

// The last column should not have a gutter.
// Respectively, $gutter defaults to 0 in this mixin.
=last-column($colspan, $device: default-device(), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $gutter: 0, $left-gutter: false, $subtract-border-from: false)
  +column($colspan, $device, $padding, $differing-right-padding, $border-width, $differing-right-border-width, $gutter, $left-gutter, $subtract-border-from)

// The only difference between the last and other columns is that the last column has margin-right set to 0.
=last
  margin-right: 0

// A row spans the whole grid width, i.e. it is the only column in a row. This is just a more elegant way for writing +last-column($grid-columns).
=row($device: default-device(), $colspan: grid-columns($device), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $gutter: 0, $left-gutter: false, $subtract-border-from: false)
  +last-column($colspan, $device, $padding, $differing-right-padding, $border-width, $differing-right-border-width, $gutter, $left-gutter, $subtract-border-from)

// Intended for use with percentage values only
// Recalculates $colspan and $gutter so that it appears as if the percentages of your nested column were relative to its grand-parent.
// The parameters are the same of =column, except for a second mandatory parameter $parent-colspan.
=fluid-sub-column($colspan, $parent-colspan, $device: default-device(), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $gutter: grid-gutter-width($device), $left-gutter: false, $subtract-border-from: false)
  +column-behavior
  +column-metrics($colspan, $device, $padding, $differing-right-padding, $border-width, $differing-right-border-width, $gutter, $left-gutter, $subtract-border-from: $subtract-border-from, $parent-colspan: $parent-colspan)

// Use this mixin for your (none-floating) grid container.
// By default, it spans the whole grid-width and is centered.
// Unlike with columns, paddings and borders of a container do not affect its inner width.
// Clearfixing has to be done in order to enforce the container to enclose its content.
=grid-container($device: default-device(), $colspan: grid-columns($device), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $left-margin: auto, $right-margin: auto)
  +column-metrics($colspan, $device, $padding, $differing-right-padding, $border-width, $differing-right-border-width, $right-margin, $left-margin, true)
  +clearfix

// Internal Methods
//=================
=column-behavior
  float: left

=column-metrics($column-width, $device: default-device(), $padding: 0, $differing-right-padding: false, $border-width: 0, $differing-right-border-width: false, $gutter: grid-gutter-width($device), $left-gutter: false, $container: false, $subtract-border-from: false, $parent-colspan: false)
  // Convert column counts to widths with unit
  $column-width: colspan-to-width($column-width, $device)
  $padding: colspan-to-width($padding, $device, $include-last-gutter: true)
  $differing-right-padding: colspan-to-width($differing-right-padding, $device, $include-last-gutter: true)
  $border-width: colspan-to-width($border-width, $device, $include-last-gutter: true)
  $differing-right-border-width: colspan-to-width($differing-right-border-width, $device, $include-last-gutter: true)
  @if is-column-count($gutter)
    // It is assumed that the original gutter should also be preserved in addition to the one of the last column
    $gutter: grid-gutter-width($device) + colspan-to-width($gutter, $device, $include-last-gutter: true)
  @if is-column-count($left-gutter)
    $left-gutter: colspan-to-width($left-gutter, $device, $include-last-gutter: true)

  // Calculate derived metrics
  $right-border-width: right-value($border-width, $differing-right-border-width)
  $border-width-sum: left-and-right-sum($border-width, $differing-right-border-width)
  $left-padding: if(($subtract-border-from == 'padding' or $subtract-border-from == 'left-padding') and $padding > 0, $padding - $border-width, $padding)
  $right-padding: right-value($padding, $differing-right-padding)
  $right-padding: if(($subtract-border-from == 'padding' or $subtract-border-from == 'right-padding') and $padding > 0, $right-padding - $right-border-width, $right-padding)
  $padding-sum: left-and-right-sum($left-padding, $right-padding)

  // Recalculate Column width for fluid sub columns
  @if $parent-colspan
    $parent-width: colspan-to-width($parent-colspan, $device)
    $column-width: ($column-width / $parent-width) * 100%
    $gutter: ($gutter / $parent-width) * 100%

  // Setting width
  @if $container
    // Paddings and borders do not affect the inner width of a container.
    width: $column-width
  @else
    // Paddings and borders do not affect the outer width of a column.
    @if $grid-box-sizing == 'border-box'
      width: $column-width
    @else
      width: $column-width - $padding-sum - $border-width-sum

  // Setting other box attributes
  padding:
    left: $left-padding
    right: $right-padding
  border:
    left-width: $border-width
    right-width: $right-border-width
  @if type_of($left-gutter) == number
    margin-left: if(($subtract-border-from == 'gutter' or $subtract-border-from == 'left-gutter') and $left-gutter > 0, $gutter - $border-width, $left-gutter)
  @else if $left-gutter
    margin-left: $left-gutter
  @if type_of($gutter) == number
    margin-right: if(($subtract-border-from == 'gutter' or $subtract-border-from == 'right-gutter') and $gutter > 0, $gutter - $right-border-width, $gutter)
  @else if $gutter
    margin-right: $gutter

@function colspan-to-width($colspan, $device: default-device(), $include-last-gutter: false)
  @if is-column-count($colspan)
    @return column-count-to-width($colspan, $device, $include-last-gutter)
  @else
    @return $colspan

@function is-column-count($colspan)
  @if type_of($colspan) == 'number'
    @if unitless($colspan) and $colspan > 0
      @return true
  @return false

@function column-count-to-width($column-count, $device: default-device(), $include-last-gutter: false)
  @if $include-last-gutter
    @return (grid-column-width($device) + grid-gutter-width($device)) * $column-count
  @else
    @return grid-column-width($device) * $column-count + grid-gutter-width($device) * ($column-count - 1)

// adds to comparable values or doubles the first one
@function left-and-right-sum($value, $differing-right-value)
  @if type-of($differing-right-value) == number
    @if comparable($value, $differing-right-value)
      @return $value + $differing-right-value
    @else
      @warn "It is not possible to compute the sum of #{$value} and #{$differing-right-value}. Please make them comparable. Meanwhile, the result is set to #{$value * 2}."
  @return $value * 2

// returns value unless numeric differing-right-value is given
@function right-value($value, $differing-right-value: false)
  @if type-of($differing-right-value) == number
    @return $differing-right-value
  @else
    @return $value
